package com.ryder.petmatediarybackend.common.interceptor;

import cn.dev33.satoken.stp.StpUtil;
import com.ryder.petmatediarybackend.common.util.IpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 访问日志拦截器
 * 记录每个请求的详细信息：方法、路径、IP、用户、状态码、耗时
 *
 * @author Ryder
 * @since 1.0
 */
/**
 * 描述: 访问日志拦截器
 *      记录每个请求的详细信息：方法、路径、IP、用户、状态码、耗时
 * @author Ryder
 * @version 1.0
 * @since 1.0
 * 更新日期: 2025/10/26
 */
@Slf4j
@Component
public class AccessLogInterceptor implements HandlerInterceptor {

    private static final String START_TIME_ATTR = "startTime";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 记录请求开始时间
        request.setAttribute(START_TIME_ATTR, System.currentTimeMillis());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                                Object handler, Exception ex) {
        // 计算耗时
        Long startTime = (Long) request.getAttribute(START_TIME_ATTR);
        long duration = startTime != null ? System.currentTimeMillis() - startTime : 0;

        // 获取请求信息
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String ip = IpUtil.getClientIp(request);
        int status = response.getStatus();
        
        // 获取用户信息（如果已登录）
        String userId = "guest";
        try {
            if (StpUtil.isLogin()) {
                userId = StpUtil.getLoginIdAsString();
            }
        } catch (Exception e) {
            // 未登录或获取失败，使用默认值
        }

        // 记录访问日志
        log.info("Access | {} {} | IP: {} | User: {} | Status: {} | Duration: {}ms",
                method, uri, ip, userId, status, duration);

        // 如果有异常，记录异常信息
        if (ex != null) {
            log.error("Request error | {} {} | IP: {} | User: {} | Error: {}",
                    method, uri, ip, userId, ex.getMessage(), ex);
        }
    }
}
